﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using Engine.Entities.Character;
using FrenzyIsland.UI;
using System.Linq;

public class UIMenuPartyCtrl : MonoBehaviour {

    private bool requireRefresh = false;

    #region private

    private UIPartyItem SelectedParty { get; set; }

    private int cont = 0;
    private List<GameObject> ListParty = new List<GameObject>();
    private List<GameObject> ListDetail = new List<GameObject>();

    private GameObject uiroot;
    private FrenzyPeopleController peopleCtrl;
    private GameObject voxelWorld;
    private GuiManager guiManager;

    private const string tableName = "table";
    private UITable tblDetail;
    private UITable tblParty;

    #endregion private

    #region public

    [System.Serializable]
    public class Accoppiamento
    {
        public GameObject AccoppiamentoContainer;
        public GameObject SelectedMale;
        public GameObject SelectedFemale;
        public UIButton ButtonCouple;
    }
    public Accoppiamento UIAccoppiamento;

    [System.Serializable]
    public class UIScrollViews
    {
        public GameObject scrollParty;
        public GameObject scrollDetail;
    }
    public UIScrollViews scrollViewContainer = new UIScrollViews();

    [System.Serializable]
    public class UIItem
    {
        public GameObject partyItem;
        public GameObject detailItem;
        public GameObject detailItemAdd;
        public GameObject menuAddItem;
        public GameObject menuCharacterAdd;
    }
    public UIItem uiItems;

    [System.Serializable]
    public class UIButtons
    {
        public GameObject bntStatus;
        public GameObject btnAddParty;
        public GameObject btnDelParty;
        //public GameObject btnCaccia;
    }
    public UIButtons uiButtons;

    public GameObject InfoLabel;
    public GameObject DetailContainer;
   
    public float alfaDisabled = 0.3f;
    public int MAX_ITEM_PER_PARTY = 3;

    // Maschio selezionato per l'accoppiamento 
    internal UICharacterItem SelectedMale { 
        get { return selectedMale; } 
        set {
            if (selectedMale == value) return;
            UpdateSelectedCharacter(value, UIAccoppiamento.SelectedMale, GenderEnum.Male);
        } 
    }
    private UICharacterItem selectedMale = null;

    // Femmina selezionata per l'accoppiamento
    internal UICharacterItem SelectedFemale
    {
        get { return selectedFemale; }
        set {
            if (selectedFemale == value) return;
            UpdateSelectedCharacter(value, UIAccoppiamento.SelectedFemale, GenderEnum.Female);
        }
    }
    private UICharacterItem selectedFemale = null;

    #endregion public

    void Awake()
    {
        voxelWorld = GameObject.FindGameObjectWithTag("VoxelWorld");
        uiroot = GameObject.FindGameObjectWithTag("UI");
        peopleCtrl = voxelWorld.GetComponent<FrenzyPeopleController>();
        guiManager = uiroot.GetComponent<GuiManager>();
    }

	void Start () {

        requireRefresh = true;

        //IsMenuPartyEnabled = false;

        tblDetail = scrollViewContainer.scrollDetail.transform.FindChild(tableName).GetComponent<UITable>();
        tblParty = scrollViewContainer.scrollParty.transform.FindChild(tableName).GetComponent<UITable>();
    }
	
	void Update () {

        if( requireRefresh )
        {
            //imposto lo stato dei bottoni nella barra
            setEnableButton(uiButtons.btnDelParty, SelectedParty != null);
            setEnableButton(uiButtons.bntStatus, SelectedParty != null);

            //imposto il bottone
            if (selectedMale != null && selectedFemale != null)
            {
                UIAccoppiamento.ButtonCouple.GetComponent<BoxCollider>().enabled = true;
                UIAccoppiamento.ButtonCouple.SetState(UIButtonColor.State.Normal, true);
                UIAccoppiamento.ButtonCouple.state = UIButtonColor.State.Normal;
            }
            else
            {
                UIAccoppiamento.ButtonCouple.GetComponent<BoxCollider>().enabled = false;
                UIAccoppiamento.ButtonCouple.SetState(UIButtonColor.State.Disabled, true);
                UIAccoppiamento.ButtonCouple.state = UIButtonColor.State.Disabled;
            }
            UIAccoppiamento.ButtonCouple.UpdateColor(true);

            DetailContainer.SetActive(SelectedParty != null);
            InfoLabel.SetActive(SelectedParty == null);
            tblDetail.Reposition();

            //il bottone caccia è attivo solo se almeno un elemento è selezionato
            //setEnableButton(uiButtons.btnCaccia, SelectedMale != null || SelectedFemale != null);
        }

    }

    // funzione richiamata dall'update per abilitare i bottoni superiori
    private void setEnableButton(GameObject btn, bool value)
    {
        if (btn == null) return;

        UIWidget widget = btn.GetComponent<UIWidget>();
        UIButton uibutton = btn.transform.FindChild("button").GetComponent<UIButton>();
        widget.alpha = value ? 1 : alfaDisabled;
        uibutton.enabled = value;
    }

    // Funzione chiamata dal setter per modificare il personaggio selezionato </summary>
    private void UpdateSelectedCharacter(UICharacterItem selected, GameObject container, GenderEnum gender)
    {
        if (selected != null)
        {
            // sto selezionando un individuo

            //creo una copia dell'oggetto selezionato
            GameObject newgameobject = Instantiate(uiItems.detailItem);
            UICharacterItem.CreateOrSetComponent(newgameobject, selected.SteveBrain, peopleCtrl, false, false);

            //cancello la UIDragScrollView dalla copia (frontendismo)
            DestroyImmediate( newgameobject.GetComponent<UIDragScrollView>() );
           
            //deseleziono il vecchio, copio il riferimento del nuovo
            string name = "";
            if (gender == GenderEnum.Male)
            {
                if (selectedMale != null)
                    DestroyImmediate(selectedMale.gameObject);

                selectedMale = newgameobject.GetComponent<UICharacterItem>();
                name = "selectedMale";
            }
            else
            {
                if(selectedFemale!= null)
                    DestroyImmediate(selectedFemale.gameObject);
                selectedFemale = newgameobject.GetComponent<UICharacterItem>();
                name = "selectedFemale";
            }

            newgameobject.transform.parent = container.transform;
            newgameobject.transform.localPosition = new Vector3(0, 0, 0);
            newgameobject.transform.localScale = new Vector3(1, 1, 1);
            newgameobject.name = name;
        }
        else
        {
            if (gender == GenderEnum.Male)
            {
                if(selectedMale!= null)
                    DestroyImmediate(selectedMale.gameObject);

                selectedMale = null;
            }
            else
            {
                if (selectedFemale != null)
                    DestroyImmediate(selectedFemale.gameObject);

                selectedFemale = null;
            }
        }

        requireRefresh = true;
    }

    // Carica i party all'interno della scrollview party
    internal void LoadParty()
    {
        Debug.Log("LoadParty");

        //DEBUG_DestroyChildrenTable();

        tblDetail = scrollViewContainer.scrollDetail.transform.FindChild(tableName).GetComponent<UITable>();
        tblParty = scrollViewContainer.scrollParty.transform.FindChild(tableName).GetComponent<UITable>();

        //clear party
        foreach (GameObject item in ListParty) DestroyImmediate(item);
        ListParty.Clear();

        //clear detail
        foreach (GameObject item in ListDetail) DestroyImmediate(item);
        ListDetail.Clear();

        //load
        Debug.Log("Carico " + peopleCtrl.PartyList.Count + " party");
        cont = 0;
        foreach (PartyController party in peopleCtrl.PartyList)
        {
            GameObject newItem = AddItem(uiItems.partyItem, scrollViewContainer.scrollParty, tblParty);

            UIPartyItem uipartyitem = newItem.GetComponent<UIPartyItem>();
            uipartyitem.PartyController = party;
            ListParty.Add(newItem);

            if( party == null )
            {
                Debug.LogError("Perchè questo oggetto non ha un party controller????");
                uipartyitem.IsSelected = true;
            }

            UIButton button = newItem.GetComponent<UIButton>();
            EventDelegate del = new EventDelegate(this, "PartyClick");
            del.parameters[0].value = uipartyitem;
            button.onClick.Add(del);

            cont++;
        }

        tblParty.Reposition();
        tblParty.repositionNow = true;

    }

    // cambio l'icona in base allo stato della comitiva
    private void SetImageStatus() {
        UISprite spriteToggleStatus = uiButtons.bntStatus.transform.FindChild("sprite").GetComponent<UISprite>();
        UILabel labelToggleStatus = uiButtons.bntStatus.transform.FindChild("label").GetComponent<UILabel>();

        if (!SelectedParty.PartyController.havingFun) { 
            spriteToggleStatus.spriteName = "peroni-cassa";
            labelToggleStatus.text = "Divertitevi!";
        }else{
            spriteToggleStatus.spriteName = "hammer";
            labelToggleStatus.text = "Lavorate!";
        }

        spriteToggleStatus.MarkAsChanged();
    }

    // Carico le persone nel pannello sulla sinistra
    public void LoadDetail(PartyController party){
        UIButton button = null; EventDelegate ed = null;
        UITable table = scrollViewContainer.scrollDetail.transform.FindChild("table").GetComponent<UITable>();

        foreach (GameObject item in ListDetail)
            DestroyImmediate(item);
        ListDetail.Clear();

        //aggiungo gli elementi nel partycontroller
        UICharacterItem charItem = null;
        cont = 0;
        foreach (SteveBrain brain in party.PeopleInParty)
        {
            //aggiunge l'elemento
            GameObject character = AddItem(uiItems.detailItem, scrollViewContainer.scrollDetail, table);
            charItem = UICharacterItem.CreateOrSetComponent(character, brain, peopleCtrl, true, false);
            ListDetail.Add(character);

            //assegno la callback per aggiornare la lista dei dettagli al kick
            charItem.SetOnKick(new UICharacterItem.SimpleDelegate(OnKick));

            //assegno l'evento per selezionare il padre e la madre
            button = character.GetComponent<UIButton>();
            ed = new EventDelegate(this, "DetailClick");
            ed.parameters[0].value = charItem;

            button.onClick.Add(ed);

            cont++;
        }

        //aggiungo un elemento per inserire nuovi elementi solo se < al maxsizeparty
        if ( cont < peopleCtrl.SizeParty )
        {
            //istanzio e imposto
            GameObject addItem = AddItem(uiItems.detailItemAdd, scrollViewContainer.scrollDetail, table);
            UICharacterItem addCharItem = UICharacterItem.CreateOrSetComponent(addItem, null, peopleCtrl, false, false);

            //imposto uno specifico evento
            button = addCharItem.GetComponent<UIButton>();
            ed = new EventDelegate(this, "AddElement_Click");
            button.onClick.Add(ed);
            ListDetail.Add(addItem);
        }
        
        //riposiziono la tabella
        table.Reposition();
        table.transform.localPosition = new Vector3(table.transform.localPosition.x, 0, table.transform.localPosition.z);
    }

    // Seleziono il personaggio per l'accoppiamento in base al sesso
    public void DetailClick(UICharacterItem detailSelected)
    {
        switch (detailSelected.SteveModel.Gender)
        {
            case Engine.Entities.Character.GenderEnum.Male:
                SelectedMale = detailSelected;
                break;
            case Engine.Entities.Character.GenderEnum.Female:
                SelectedFemale = detailSelected;
                break;
        }

        requireRefresh = true;
    }

    #region Eventi

    //Evento generato dal click su un party nella scrollview
    public void PartyClick(UIPartyItem selectedObject)
    {
        //Deseleziono prima il vecchio oggetto selezionato l'oggetto
        if (SelectedParty != null) SelectedParty.ToggleSelection();

        //deseleziono anche i personaggi selezionati per l'accoppiamento
        SelectedFemale = null;
        SelectedMale = null;

        //seleziona il nuovo oggetto 
        SelectedParty = selectedObject;
        SelectedParty.ToggleSelection();

        //Imposto l'immagine dello stato della comitiva        
        SetImageStatus();
        
        //Carico le persone nel party
        if (selectedObject.PartyController != null)
        {
            LoadDetail(selectedObject.PartyController);
        }
        else
        {
            Debug.LogError("Perchè questo oggetto non ha un party controller????");
        }

    }

    //Evento sul bottone di chiusura
    public void Close_Click()
    {
        //guiManager.CloseMenu(this.gameObject);
    }

    // Evento creato ed attaccato sull'elemento per aggiungere nuovi elementi al party
    public void AddElement_Click()
    {
        GameObject menu = Instantiate(uiItems.menuAddItem);
        menu.transform.parent = uiroot.transform;
        menu.transform.localScale = new Vector3(1, 1, 1);
        menu.transform.localPosition = new Vector3(0,0,0);
        menu.name = "UIMenuAddCharacterInParty";

        UIMenuAddCharacterPartyCtrl.SetComponent(menu, new UIMenuAddCharacterPartyCtrl.AddDelegate(AddElement_Click_OK),
                                                 "Seleziona gli individui da aggiungere nella comitiva selezionata", SelectedParty.PartyController);

        menu.SetActive(true);
    }

    // callback per l'aggiunta di nuovi elementi nella comitiva
    public void AddElement_Click_OK(UICharacterItem[] listSelected)
    {
        List<SteveBrain> lstSteveBrain = (from UICharacterItem item in listSelected
                                          select item.SteveBrain).ToList<SteveBrain>();

        peopleCtrl.AddInParty(lstSteveBrain, SelectedParty.PartyController);

        //carico nuovamente i detail
        LoadDetail(SelectedParty.PartyController);
        
    }

    // Scioglie la comitiva selezionata
    public void SciogliComitiva_Click()
    {
        //guiManager.ShowMessageBox("Sei sicuro di voler eliminare la comitiva selezionata?",
        //                          new GuiManager.SimpleDelegate(SciogliComitiva_SI), 
        //                          new GuiManager.SimpleDelegate(SciogliComitiva_NO) );
    }

    // Callback della messagebox
    public void SciogliComitiva_SI()
    {
        peopleCtrl.DestroyParty(SelectedParty.PartyController);
        SelectedParty = null;
        LoadParty();
    }

    public void SciogliComitiva_NO()
    {

    }

    public void NewParty_Click()
    {
        GameObject menu = Instantiate(uiItems.menuAddItem);
        menu.transform.parent = uiroot.transform;
        menu.transform.localScale = new Vector3(1, 1, 1);
        menu.transform.localPosition = new Vector3(0, 0, 0);
        menu.name = "UIMenuAddCharacterInParty";

        UIMenuAddCharacterPartyCtrl.SetComponent(menu, new UIMenuAddCharacterPartyCtrl.AddDelegate(NewParty_Click_OK),
                                                 "Seleziona gli individui per la nuova comitiva");

        menu.SetActive(true);
    }

    public void NewParty_Click_OK(UICharacterItem[] listToAdd)
    {
        List<SteveBrain> lst = (from UICharacterItem item in listToAdd
                                     select item.SteveBrain).ToList<SteveBrain>();
        peopleCtrl.AddInParty(lst);
        LoadParty();
    }

    //Evento click del cambio stato della comitiva
    public void BtnStatus_Click(){
        //cambia lo status alla comitiva
        
        SelectedParty.PartyController.havingFun = !SelectedParty.PartyController.havingFun;
        //notifico il cambiamento dello status
        SelectedParty.RefreshStatus();
        SetImageStatus();
    }

    //Funzione per accoppiare 2 personaggi
    public void Accoppia_Click()
    {
        Debug.Log("CALL: Accoppia_Click");

        SteveBrain newBrain = peopleCtrl.Couple(SelectedMale.SteveModel, SelectedFemale.SteveModel);

        SelectedMale = null;
        SelectedFemale = null;
      
        //istanzia il menu per l'accoppiamento
        GameObject menu = Instantiate(uiItems.menuCharacterAdd);
        menu.transform.parent = uiroot.transform;
        menu.transform.localPosition = Vector3.zero;
        menu.transform.localScale = Vector3.one;
        menu.SetActive(true);

        //istanzia un nuovo gameobject da visualizzare nella schermata
        GameObject newCharacter = Instantiate(uiItems.detailItem);
        UICharacterItem.CreateOrSetComponent(newCharacter, newBrain, peopleCtrl, false, false);
        menu.GetComponent<UIMessageBoxAddCharacter>().SetItem(newCharacter);

        LoadDetail(SelectedParty.PartyController);
    }
    
    //evento richiamato dal bottone del kick. Assegnata la callback in fase di creazione
    private void OnKick()
    {
        Debug.Log("CALL: onKick");

        //se non ci sono più persone nel party, peopleCtrl cancella anche il party
        if( SelectedParty.PartyController.PeopleInParty.Count == 0 )
        {
            SelectedParty = null;
            LoadParty();
            requireRefresh = true;
        }
        else
        {
            LoadDetail(SelectedParty.PartyController);
        }
    }

    #endregion Eventi

    // Funzione generica per aggiungere un nuovo elemento nella scrollview passata come parametro
    private GameObject AddItem( GameObject prefab, GameObject scrollview, UITable table)
    {
        Debug.Assert(scrollview != null, "scrollview is null");

        GameObject newItem = Instantiate(prefab);

        Debug.Assert(table != null, "table is null");

        newItem.transform.parent = table.transform;
        newItem.transform.localScale = new Vector3(1, 1, 1);
        newItem.transform.localScale = new Vector3(1, 1, 1);
        newItem.transform.localPosition = new Vector3(0,0,0);
        
        return newItem;
    }
}
